package com.raidpoints.client;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ScrollPanel;

public class LootEditor extends DialogBox {
	RaidPoints rp;
	FlexTable lootTable;
	private ListBox destBox;

	ArrayList<lootitem> loot;
	ArrayList<String> destList;
	ArrayList<String> encList;
	HashSet<lootitem> updated;
	private ListBox bossBox;
	private Button bossButton;
	private Button destButton;
	private Button importButton;
	private ScrollPanel lootPan;
	private Button newButton;
	private Button saveButton;
	private AsyncCallback<ArrayList<lootitem>> lootCallback;
	private AsyncCallback<ArrayList<String>> encCallback;
	private AsyncCallback<ArrayList<String>> destCallback;
	private Button poolButton;

	public LootEditor(RaidPoints mrp) {
		rp = mrp;
		loot = new ArrayList<lootitem>();
		lootTable = new FlexTable();
		updated = new HashSet<lootitem>();
		destList = new ArrayList<String>();
		encList = new ArrayList<String>();
		setHTML("Loot Editor");
		setWidth("502px");
		LayoutPanel layoutPanel = new LayoutPanel();
		setWidget(layoutPanel);
		layoutPanel.setSize("500px", "445px");

		destBox = new ListBox();
		destBox.setWidth("200px");
		layoutPanel.add(destBox);
		layoutPanel.setWidgetLeftWidth(destBox, 17.0, Unit.PX, 220.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(destBox, 12.0, Unit.PX, 24.0, Unit.PX);

		bossBox = new ListBox();
		bossBox.setWidth("200px");
		layoutPanel.add(bossBox);
		layoutPanel.setWidgetLeftWidth(bossBox, 17.0, Unit.PX, 220.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(bossBox, 55.0, Unit.PX, 24.0, Unit.PX);

		bossButton = new Button("New Boss");
		layoutPanel.add(bossButton);
		layoutPanel.setWidgetLeftWidth(bossButton, 234.0, Unit.PX, 81.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(bossButton, 51.0, Unit.PX, 28.0, Unit.PX);

		destButton = new Button("New Dest");
		layoutPanel.add(destButton);
		layoutPanel.setWidgetLeftWidth(destButton, 234.0, Unit.PX, 81.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(destButton, 8.0, Unit.PX, 28.0, Unit.PX);

		importButton = new Button("Import");
		layoutPanel.add(importButton);
		layoutPanel.setWidgetLeftWidth(importButton, 321.0, Unit.PX, 81.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(importButton, 51.0, Unit.PX, 28.0, Unit.PX);

		lootPan = new ScrollPanel();
		layoutPanel.add(lootPan);
		layoutPanel.setWidgetLeftWidth(lootPan, 17.0, Unit.PX, 418.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(lootPan, 85.0, Unit.PX, 265.0, Unit.PX);

		newButton = new Button("New Item");
		layoutPanel.add(newButton);
		layoutPanel.setWidgetLeftWidth(newButton, 17.0, Unit.PX, 81.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(newButton, 356.0, Unit.PX, 28.0, Unit.PX);

		saveButton = new Button("Save");
		layoutPanel.add(saveButton);
		layoutPanel.setWidgetLeftWidth(saveButton, 163.0, Unit.PX, 81.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(saveButton, 356.0, Unit.PX, 28.0, Unit.PX);

		Button closeButton = new Button("Close");
		layoutPanel.add(closeButton);
		layoutPanel.setWidgetLeftWidth(closeButton, 200.0, Unit.PX, 81.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(closeButton, 406.0, Unit.PX, 28.0, Unit.PX);
		
		poolButton = new Button("Pools");
		layoutPanel.add(poolButton);
		layoutPanel.setWidgetLeftWidth(poolButton, 408.0, Unit.PX, 81.0, Unit.PX);
		layoutPanel.setWidgetTopHeight(poolButton, 51.0, Unit.PX, 28.0, Unit.PX);

		lootPan.add(lootTable);
		bossButton.setEnabled(false); importButton.setEnabled(false); poolButton.setEnabled(false);
		newButton.setEnabled(false); saveButton.setEnabled(false);


		closeButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				hide();				
			}
		});

		newButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				lootitem li = new lootitem();
				li.name = "New Item " + loot.size();
				li.encounterid = Integer.parseInt(encList.get(bossBox.getSelectedIndex()-1).split(":;:")[0]);
				loot.add(li); updated.add(li);
				DrawTable();
				lootPan.scrollToBottom();
			}
		});

		saveButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				if(updated.size() == 0) return;
				ArrayList<lootitem> tbs = new ArrayList<lootitem>();
				tbs.addAll(updated);
				saveButton.setEnabled(false);
				loot.clear(); 
				updated.clear();
				DrawTable();
				rp.rpsvc.EditLoot(tbs, lootCallback);
			}
		});

		destButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				NewBox nb = new NewBox(true);
				nb.center(); nb.show();
			}
		});

		bossButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				if(destBox.getSelectedIndex() < 1) return;
				NewBox nb = new NewBox(false);
				nb.center(); nb.show();
			}
		});

		importButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				if(destBox.getSelectedIndex() < 1) return;
				ImportBox ib = new ImportBox();
				ib.center(); ib.show();
			}
		});
		
		poolButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				if(destBox.getSelectedIndex() < 1) return;
				PoolBox pb = new PoolBox();
				pb.center(); pb.show();
			}
		});

		destCallback = new AsyncCallback<ArrayList<String>>(){

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onSuccess(ArrayList<String> result) {
				if(result == null) return;
				destList.clear();
				destList.addAll(result);
				destBox.clear();
				destBox.addItem("Select Dest:");
				for(String s : destList) destBox.addItem(s.split(":;:")[1]);
			}

		};

		encCallback = new AsyncCallback<ArrayList<String>>(){

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onSuccess(ArrayList<String> result) {
				if(result == null) return;
				encList.clear();
				encList.addAll(result);
				bossBox.clear();
				bossBox.addItem("Select Encounter:");
				for(String s : encList) bossBox.addItem(s.split(":;:")[1]);
			}

		};

		lootCallback = new AsyncCallback<ArrayList<lootitem>>(){

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onSuccess(ArrayList<lootitem> result) {
				if(result == null) return;
				loot.clear();
				loot.addAll(result);
				updated.clear();
				DrawTable();
				saveButton.setEnabled(true);
			}

		};

		destBox.addChangeHandler(new ChangeHandler(){
			@Override
			public void onChange(ChangeEvent event) {
				int sel = destBox.getSelectedIndex();
				loot.clear();
				bossBox.clear();
				newButton.setEnabled(false); saveButton.setEnabled(false);
				updated.clear();
				DrawTable();
				if(sel < 1){
					bossButton.setEnabled(false); importButton.setEnabled(false); poolButton.setEnabled(false);
					return;
				}
				bossButton.setEnabled(true); importButton.setEnabled(true); poolButton.setEnabled(true);
				rp.rpsvc.GetEncounters(Integer.parseInt(destList.get(sel-1).split(":;:")[0]), encCallback);
			}
		});

		bossBox.addChangeHandler(new ChangeHandler(){
			@Override
			public void onChange(ChangeEvent event) {
				int sel  = bossBox.getSelectedIndex();
				loot.clear();
				updated.clear();
				DrawTable();
				if(sel < 1){
					newButton.setEnabled(false); saveButton.setEnabled(false);
					return;
				}
				newButton.setEnabled(true); saveButton.setEnabled(true);
				rp.rpsvc.GetEditableLoot(Integer.parseInt(encList.get(sel-1).split(":;:")[0]),lootCallback);
			}
		});

		rp.rpsvc.GetAllDest(destCallback);
	}

	void DrawTable(){
		lootTable.clear();
		lootTable.setWidget(0, 0, new Label("Name"));
		lootTable.setWidget(0, 1, new Label("Wowhead ID"));

		for(int i = 0; i < loot.size(); i++){
			final int cr = i;
			final TextBox nameBox = new TextBox();
			final TextBox widBox = new TextBox();
			Button xButton = new Button("-");
			nameBox.setWidth("230px"); widBox.setWidth("100px");
			lootTable.setWidget(i+1, 0, nameBox);
			lootTable.setWidget(i+1, 1, widBox);
			lootTable.setWidget(i+1, 2, xButton);
			nameBox.setText(loot.get(i).name); widBox.setText(loot.get(i).wowheadid);

			xButton.addClickHandler(new ClickHandler(){
				@Override
				public void onClick(ClickEvent event) {				
					loot.get(cr).name = ":X:";
					updated.add(loot.get(cr));
					loot.remove(cr);
					DrawTable();
				}
			});

			nameBox.addChangeHandler(new ChangeHandler(){
				@Override
				public void onChange(ChangeEvent event) {
					String name = nameBox.getText();
					if(name.length() > 50){
						name = name.substring(0,49);
						nameBox.setText(name);
					}
					loot.get(cr).name = name;
					updated.add(loot.get(cr));
				}	
			});

			widBox.addChangeHandler(new ChangeHandler(){
				@Override
				public void onChange(ChangeEvent event) {
					String wid = widBox.getText();
					if(!wid.matches("[a-zA-Z0-9]*")){
						wid = "";
						widBox.setText("");
					}
					loot.get(cr).wowheadid = wid;
					updated.add(loot.get(cr));
				}	
			});
		}
	}

	public class NewBox extends DialogBox{

		NewBox(final boolean dest){
			if(dest) setHTML("New Destination");
			else setHTML("New Boss");
			HorizontalPanel hpan = new HorizontalPanel();
			hpan.setSpacing(2);
			setWidget(hpan);
			final ArrayList<gameinfo> glist = new ArrayList<gameinfo>();
			final TextBox nameBox = new TextBox(); nameBox.setWidth("120px");
			final ListBox gameBox = new ListBox();
			Button addButton = new Button("Add");
			Button closeButton = new Button("Cancel");
			hpan.add(new Label("Name: ")); hpan.add(nameBox);
			if(dest) hpan.add(gameBox);

			hpan.add(addButton); hpan.add(closeButton);

			closeButton.addClickHandler(new ClickHandler(){
				@Override
				public void onClick(ClickEvent event) {
					hide();
				}
			});

			addButton.addClickHandler(new ClickHandler(){
				@Override
				public void onClick(ClickEvent event) {
					if(!nameBox.getText().matches("[a-zA-Z0-9,:;'\\)\\( ]{2,50}")){
						Window.alert("Invalid name");
						return;
					}

					AsyncCallback<String> addCallback = new AsyncCallback<String>(){

						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onSuccess(String result) {
							if(result == null) return;
							if(result.equals("")) return;
							if(dest){
								destList.add(result);
								destBox.addItem(result.split(":;:")[1]);
							}
							else{
								encList.add(result);
								bossBox.addItem(result.split(":;:")[1]);
							}
							hide();
						}

					};
					if(dest) rp.rpsvc.AddDestination(glist.get(gameBox.getSelectedIndex()).ngsid, nameBox.getText(), addCallback);
					else rp.rpsvc.AddEncounter(Integer.parseInt(destList.get(destBox.getSelectedIndex()-1).split(":;:")[0]), nameBox.getText(), addCallback);
				}
			});

			if(dest){
				AsyncCallback<ArrayList<gameinfo>> gameCallback = new AsyncCallback<ArrayList<gameinfo>>(){

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}

					@Override
					public void onSuccess(ArrayList<gameinfo> result) {
						if(result == null) {hide(); return;}
						if(result.size() == 0) {hide(); return;}
						glist.addAll(result);
						for(gameinfo g : glist) gameBox.addItem(g.game);
					}

				};
				rp.rpsvc.GetGames(gameCallback);				
			}

		}
	}

	public class PoolBox extends DialogBox{
		ListBox poolList;
		ArrayList<Integer> idList;
		VerticalPanel vpan;

		PoolBox(){
			setHTML("Change Destination Pools");
			vpan = new VerticalPanel();
			setWidget(vpan);

			idList = new ArrayList<Integer>();
			poolList = new ListBox(true);
			poolList.setVisibleItemCount(7);
			poolList.setHeight("150px");
			poolList.setWidth("200px");
			vpan.add(poolList);

			AsyncCallback<ArrayList<String>> poolCallback = new AsyncCallback<ArrayList<String>>(){
				@Override
				public void onFailure(Throwable caught) {
					// TODO Auto-generated method stub

				}

				@Override
				public void onSuccess(ArrayList<String> result) {
					for(String s : result){
						String ts = s;
						boolean sel = ts.startsWith(":;:");
						if(sel) ts = ts.substring(3);
						idList.add(Integer.parseInt(ts.split(":;:")[0]));
						poolList.addItem(ts.split(":;:")[1]);
						poolList.setItemSelected(poolList.getItemCount()-1, sel);
					}
				}
			};

			rp.rpsvc.GetAllPools(Integer.parseInt(destList.get(destBox.getSelectedIndex()-1).split(":;:")[0]), false, poolCallback);

			HorizontalPanel buttonPan = new HorizontalPanel();
			vpan.add(buttonPan);
			Button saveButton = new Button("Save");
			Button closeButton = new Button("Close");
			buttonPan.add(saveButton); buttonPan.add(closeButton);

			saveButton.addClickHandler(new ClickHandler(){
				@Override
				public void onClick(ClickEvent event) {
					ArrayList<Integer> selId = new ArrayList<Integer>();
					for(int i = 0; i < poolList.getItemCount(); i++){
						if(poolList.isItemSelected(i)) selId.add(idList.get(i));
					}
					rp.rpsvc.SetDestPools(Integer.parseInt(destList.get(destBox.getSelectedIndex()-1).split(":;:")[0]), selId, rp.stringCallback);
					hide();					
				}
			});

			closeButton.addClickHandler(new ClickHandler(){
				@Override
				public void onClick(ClickEvent event) {
					hide();					
				}
			});

		}
	}

	public class ImportBox extends DialogBox{
		TextArea importArea;

		ImportBox(){
			setHTML("Import Loot");
			//	setSize("250px","400px");
			VerticalPanel vpan = new VerticalPanel();
			setWidget(vpan);

			vpan.add(new HTML("Add items in comma-separated list of form<br>'boss name,loot name,wowhead id' (-1 for no wowhead id)"));
			importArea = new TextArea();
			importArea.setSize("270px", "380px");
			vpan.add(importArea);

			final Button mimportButton = new Button("Import");
			Button closeButton = new Button("Close");
			HorizontalPanel hpan = new HorizontalPanel(); hpan.setSpacing(2);
			hpan.add(mimportButton); hpan.add(closeButton);
			vpan.add(hpan);

			closeButton.addClickHandler(new ClickHandler(){
				@Override
				public void onClick(ClickEvent event) {
					hide();					
				}
			});

			mimportButton.addClickHandler(new ClickHandler(){
				@Override
				public void onClick(ClickEvent event) {
					String sloot = importArea.getText();
					if(!sloot.matches("([a-zA-Z0-9-:;'\\)\\( ]{1,50},[a-zA-Z0-9-:;'\\)\\( ]{1,50},[a-zA-Z0-9]*[\\r\\n]*)+")){
						Window.alert("Invalid input");
						return;
					}
					AsyncCallback<String> importCallback = new AsyncCallback<String>(){

						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onSuccess(String result) {
							int sel = destBox.getSelectedIndex();
							loot.clear();
							bossBox.clear();
							newButton.setEnabled(false); saveButton.setEnabled(false);
							updated.clear();
							DrawTable();
							if(sel < 1){
								bossButton.setEnabled(false); importButton.setEnabled(false);
								return;
							}
							bossButton.setEnabled(true); importButton.setEnabled(true);
							rp.rpsvc.GetEncounters(Integer.parseInt(destList.get(sel-1).split(":;:")[0]), encCallback);	
							hide();
						}

					};
					mimportButton.setEnabled(false);
					rp.rpsvc.ImportLoot(Integer.parseInt(destList.get(destBox.getSelectedIndex()-1).split(":;:")[0]), sloot, importCallback);
				}
			});
		}
	}

	public static class lootitem implements Serializable{
		public int id=-1; public String name=""; public String wowheadid=""; public int encounterid=-1;
	}
}
